

/*
SPSC, fifo .
entry fix size, only uint64.
*/

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

#include "ufifo.h"



int ufifo_alloc( uint32_t npwr, ufifo_t ** pret )
{
	uint32_t tsiz;
    ufifo_t * prb;

    /* check tlen, 2^n */
    tsiz = 1ull << npwr;

    /**/
    prb = (ufifo_t *)malloc( sizeof(ufifo_t) + ((tsiz - 4) * sizeof(uint64_t)) );
    if ( NULL == prb )  {
        return 2;
    }

    /**/
    prb->head = prb->tail = 0;
    prb->mask = tsiz - 1;

    /**/
    *pret = prb;
    return 0;
}



/*
data -> ring
return : tlen is ok; other fail.
*/
int ufifo_enqueue( ufifo_t * prb, uint64_t data )
{
    size_t  frees;
    uint32_t  temp;
    
    /**/
    frees = (size_t)(prb->mask - ( ( prb->head - prb->tail ) & prb->mask ) );
    if ( frees <= 0 )  {
        return -100;
    }

    /* write entry */
    temp = prb->head & prb->mask;
    prb->entrys[temp] = data;
    
    /**/
    prb->head = prb->head + 1;
    return 0;
    
}


/*
ring -> data
*/
int ufifo_dequeue( ufifo_t * prb, uint64_t * pdat )
{
    size_t  entrys;
    uint32_t  temp;
    
    /**/
    entrys = (size_t)((prb->head - prb->tail) & prb->mask);
    if ( entrys <= 0 )  {
        /* noting in ring */
        return 12;
    }

    /**/
    temp = prb->tail & prb->mask;
    *pdat = prb->entrys[temp];
    
    /**/
    prb->tail = prb->tail + 1;
    return 0;
    
}



